﻿using System;
using System.Diagnostics;
using System.Linq;
using System.Runtime.Serialization;

namespace MyHome.Server.PluginBase
{
    /// <summary>
    /// Provides a generic implementation for a plugin that processes or transforms data.
    /// </summary>
    /// <typeparam name="T">The type of data to be transformed by this plugin.</typeparam>
    /// <typeparam name="U">The type of data after processing / transformation.</typeparam>
    public abstract class ProcessingPlugin<T, U> : InputOutputPlugin<T, U>, IProcessingPlugin<T, U>
    {
        /// <summary>
        /// Gets the type of the plugin.
        /// </summary>
        /// <value>
        /// <see cref="PluginType.Processing"/>
        /// </value>
        public override PluginType PluginType
        {
            get { return PluginType.Processing; }
        }


        /// <summary>
        /// Called when data to output is received.
        /// </summary>
        /// <param name="value">The value to output.</param>
        protected override void OnSendOutput(T value)
        {
            try
            {
                Trace.TraceInformation("{0} \"{1}\", Id: {2} is processing new input: {3}", PluginType.ToString(), this, Id, value);
                var processed = Process(value);
                Trace.TraceInformation("{0} \"{1}\", Id: {2} has processed input: {3} and got: {4}", PluginType.ToString(), this, Id, value, processed);
                OnNewValue(processed);
            }
            catch
            {
                Trace.TraceError("{0} \"{1}\", Id: {2} failed to process new input: {3}", PluginType.ToString(), this, Id, value);
                State = PluginState.Error;
            }
        }

        /// <summary>
        /// Called when data to process is received.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns>The processed value.</returns>
        protected abstract U Process(T value);
    }
}